package common

import (
	"context"
	"encoding/json"
	"github.com/gorhill/cronexpr"
	"strings"
	"time"
)

//Job 定时任务
type Job struct {
	//任务名
	Name string `json:"name"`
	//shell命令
	Command string `json:"command"`
	//cron表达式
	CronExpr string `json:"cronExpr"`
}

//Repsonse 接口应答体
type Response struct {
	ErrorNo int         `json:"errNo"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

//Etcd任务事件
type JobEvent struct {
	EventType int
	Job       *Job
}

//DelJobReq 删除任务请求体
type DelJobReq struct {
	JobName string `json:"jobName"`
}

//KillJobReq 强杀任务请求体
type KillJobReq struct {
	JobName string `json:"jobName"`
}

func BuildResponse(errNo int, msg string, data interface{}) (resp []byte, err error) {

	var (
		result Response
	)

	result.ErrorNo = errNo
	result.Message = msg
	result.Data = data

	resp, err = json.Marshal(&result)

	return

}

func UnpackJob(bytes []byte) (job *Job, err error) {

	tmpJob := &Job{}
	if err = json.Unmarshal(bytes, tmpJob); err != nil {
		return
	}
	job = tmpJob

	return
}

func BuildJobEvent(eventType int, job *Job) *JobEvent {

	return &JobEvent{
		EventType: eventType,
		Job:       job,
	}
}

func ExtractJobName(jobKey string) string {
	return strings.TrimPrefix(jobKey, JOB_SAVE_DIR)
}
func ExtractKillJobName(jobKey string) string {
	return strings.TrimPrefix(jobKey, JOB_KILL_DIR)
}

//任务调度计划
type JobSchedulePlan struct {
	//调度的计划
	Job *Job
	//该计划的cron表达式
	Expr *cronexpr.Expression
	//任务下一次的执行时间
	NextTime time.Time
}

//根据任务构建任务调度计划
func BuildJobSchedulePlan(job *Job) (jobSchedulePlan *JobSchedulePlan, err error) {

	var (
		jobExpr *cronexpr.Expression
	)

	if jobExpr, err = cronexpr.Parse(job.CronExpr); err != nil {
		return
	}

	jobSchedulePlan = &JobSchedulePlan{
		Job:      job,
		Expr:     jobExpr,
		NextTime: jobExpr.Next(time.Now()),
	}

	return
}

//JobExecuteInfo 任务执行信息
type JobExecuteInfo struct {
	//执行信息所属任务
	Job *Job
	//任务的计划执行时间
	PlanTime time.Time
	//任务的实际执行时间
	RealTime time.Time
	//用于取消任务
	CancleFunc context.CancelFunc
	//取消上下文
	CancelCtx context.Context
}

//BuildJobExecuteInfo 构建任务执行信息
func BuildJobExecuteInfo(plan *JobSchedulePlan) (jobExInfo *JobExecuteInfo) {
	jobExInfo = &JobExecuteInfo{
		Job:      plan.Job,
		PlanTime: plan.NextTime,
		RealTime: time.Now(),
	}
	jobExInfo.CancelCtx, jobExInfo.CancleFunc = context.WithCancel(context.TODO())
	return
}

//JobExecuteResult 任务的执行结果
type JobExecuteResult struct {
	//任务执行信息
	JobExecuteInfo *JobExecuteInfo
	//shell执行后的错误
	Err error
	//shell执行后的输出信息
	Output []byte
	//shell执行开始时间
	StartTime time.Time
	//shell执行结束时间
	EndTime time.Time
}
